﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;

namespace Kokomo.Mirror.CliMetadata.DebugInfo
{
	public class DebugDatabase
	{
		internal DebugDatabase(string fileName)
		{
			this.FileName = fileName;

			this.SymConstantRows = new List<SymConstant>();
			this.SymDocumentRows = new List<SymDocument>();
			this.SymMethodRows = new List<SymMethod>();
			this.SymSequencePointRows = new List<SymSequencePoint>();
			this.SymScopeRows = new List<SymScope>();
			this.SymVariableRows = new List<SymVariable>();
			this.SymUsingRows = new List<SymUsing>();
		}

		public IEnumerable<IEnumerable> GetTables()
		{
			return new IEnumerable[] {
				this.SymConstantRows,
				this.SymDocumentRows,
				this.SymMethodRows,
				this.SymSequencePointRows,
				this.SymScopeRows,
				this.SymVariableRows,
				this.SymUsingRows
			};
		}

		public string FileName { get; private set; }
		public DebugDatabaseHeader Header { get; private set; }
		public List<SymConstant> SymConstantRows { get; private set; }
		public List<SymDocument> SymDocumentRows { get; private set; }
		public List<SymMethod> SymMethodRows { get; private set; }
		public List<SymSequencePoint> SymSequencePointRows { get; private set; }
		public List<SymScope> SymScopeRows { get; private set; }
		public List<SymVariable> SymVariableRows { get; private set; }
		public List<SymUsing> SymUsingRows { get; private set; }

		public byte[] SymMiscHeap { get; private set; }
		public byte[] SymStringHeap { get; private set; }

		public static DebugDatabase Load(string fileName)
		{
			if (fileName == null) throw new ArgumentNullException("fileName");

			DebugDatabase database = new DebugDatabase(fileName);
			using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
			{
				DebugDatabaseHeader header = stream.ReadStruct<DebugDatabaseHeader>(); ;
				database.Header = header;
				database.SymConstantRows.AddRange(stream.ReadStructArray<SymConstant>(header.CountOfConstants));
				database.SymDocumentRows.AddRange(stream.ReadStructArray<SymDocument>(header.CountOfDocuments));
				database.SymMethodRows.AddRange(stream.ReadStructArray<SymMethod>(header.CountOfMethods));
				database.SymSequencePointRows.AddRange(stream.ReadStructArray<SymSequencePoint>(header.CountOfSequencePoints));
				database.SymScopeRows.AddRange(stream.ReadStructArray<SymScope>(header.CountOfScopes));
				database.SymVariableRows.AddRange(stream.ReadStructArray<SymVariable>(header.CountOfVars));
				database.SymUsingRows.AddRange(stream.ReadStructArray<SymUsing>(header.CountOfUsing));
			}

			return database;
		}
	}
}
